home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet multimedia / Muzyka / Edytory sampli (probek dzwieku) / ZynAddSubFX_2.2.0 / Setup_ZynAddSubFX-2.2.0.exe / source code / Synth / PADnote.C < prev    next >
C/C++ Source or Header  |  2005-03-25  |  11KB  |  343 lines

  1. /*
  2.   ZynAddSubFX - a software synthesizer
  3.  
  4.   PADnote.C - The "pad" synthesizer
  5.   Copyright (C) 2002-2005 Nasca Octavian Paul
  6.   Author: Nasca Octavian Paul
  7.  
  8.   This program is free software; you can redistribute it and/or modify
  9.   it under the terms of version 2 of the GNU General Public License 
  10.   as published by the Free Software Foundation.
  11.  
  12.   This program is distributed in the hope that it will be useful,
  13.   but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.   GNU General Public License (version 2) for more details.
  16.  
  17.   You should have received a copy of the GNU General Public License (version 2)
  18.   along with this program; if not, write to the Free Software Foundation,
  19.   Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  20. */
  21. #include <math.h>
  22. #include "PADnote.h"
  23. #include "../Misc/Config.h"
  24.  
  25. PADnote::PADnote(PADnoteParameters *parameters, Controller *ctl_,REALTYPE freq, REALTYPE velocity, int portamento_, int midinote){
  26.     ready=0;
  27.     pars=parameters;
  28.     portamento=portamento_;
  29.     ctl=ctl_;
  30.     this->velocity=velocity;
  31.     finished_=false;
  32.     
  33.  
  34.     if (pars->Pfixedfreq==0) basefreq=freq;
  35.     else {
  36.         basefreq=440.0;
  37.         int fixedfreqET=pars->PfixedfreqET;
  38.         if (fixedfreqET!=0) {//if the frequency varies according the keyboard note 
  39.         REALTYPE tmp=(midinote-69.0)/12.0*(pow(2.0,(fixedfreqET-1)/63.0)-1.0);
  40.         if (fixedfreqET<=64) basefreq*=pow(2.0,tmp);
  41.             else basefreq*=pow(3.0,tmp);
  42.         };
  43.  
  44.     };
  45.  
  46.     firsttime=true;
  47.     released=false;
  48.     realfreq=basefreq;
  49.     NoteGlobalPar.Detune=getdetune(pars->PDetuneType
  50.         ,pars->PCoarseDetune,pars->PDetune);
  51.  
  52.  
  53.     //find out the closest note
  54.     REALTYPE logfreq=log(basefreq*pow(2.0,NoteGlobalPar.Detune/1200.0));
  55.     REALTYPE mindist=fabs(logfreq-log(pars->sample[0].basefreq+0.0001));
  56.     nsample=0;
  57.     for (int i=1;i<PAD_MAX_SAMPLES;i++){
  58.     if (pars->sample[i].smp==NULL) break;
  59.     REALTYPE dist=fabs(logfreq-log(pars->sample[i].basefreq+0.0001));
  60. //    printf("(mindist=%g) %i %g                  %g\n",mindist,i,dist,pars->sample[i].basefreq);
  61.     
  62.     if (dist<mindist){
  63.         nsample=i;
  64.         mindist=dist;
  65.     };
  66.     };
  67.  
  68.     int size=pars->sample[nsample].size;
  69.     if (size==0) size=1;
  70.     
  71.     
  72.     poshi_l=(int)(RND*(size-1));
  73.     if (pars->PStereo!=0) poshi_r=(poshi_l+size/2)%size;
  74.     else poshi_r=poshi_l;
  75.     poslo=0.0;
  76.     
  77.     tmpwave=new REALTYPE [SOUND_BUFFER_SIZE];
  78.  
  79.  
  80.     
  81.     if (pars->PPanning==0) NoteGlobalPar.Panning=RND;
  82.     else NoteGlobalPar.Panning=pars->PPanning/128.0;
  83.  
  84.     NoteGlobalPar.FilterCenterPitch=pars->GlobalFilter->getfreq()+//center freq
  85.         pars->PFilterVelocityScale/127.0*6.0*  //velocity sensing
  86.         (VelF(velocity,pars->PFilterVelocityScaleFunction)-1);
  87.  
  88.     if (pars->PPunchStrength!=0) {
  89.         NoteGlobalPar.Punch.Enabled=1;
  90.     NoteGlobalPar.Punch.t=1.0;//start from 1.0 and to 0.0
  91.     NoteGlobalPar.Punch.initialvalue=( (pow(10,1.5*pars->PPunchStrength/127.0)-1.0)
  92.         *VelF(velocity,pars->PPunchVelocitySensing) );
  93.     REALTYPE time=pow(10,3.0*pars->PPunchTime/127.0)/10000.0;//0.1 .. 100 ms
  94.     REALTYPE stretch=pow(440.0/freq,pars->PPunchStretch/64.0);
  95.     NoteGlobalPar.Punch.dt=1.0/(time*SAMPLE_RATE*stretch);
  96.     } else NoteGlobalPar.Punch.Enabled=0;
  97.  
  98.  
  99.  
  100.     NoteGlobalPar.FreqEnvelope=new Envelope(pars->FreqEnvelope,basefreq);
  101.     NoteGlobalPar.FreqLfo=new LFO(pars->FreqLfo,basefreq);
  102.     
  103.     NoteGlobalPar.AmpEnvelope=new Envelope(pars->AmpEnvelope,basefreq);
  104.     NoteGlobalPar.AmpLfo=new LFO(pars->AmpLfo,basefreq);
  105.  
  106.     NoteGlobalPar.Volume=4.0*pow(0.1,3.0*(1.0-pars->PVolume/96.0))//-60 dB .. 0 dB
  107.         *VelF(velocity,pars->PAmpVelocityScaleFunction);//velocity sensing
  108.  
  109.     NoteGlobalPar.AmpEnvelope->envout_dB();//discard the first envelope output
  110.     globaloldamplitude=globalnewamplitude=NoteGlobalPar.Volume*NoteGlobalPar.AmpEnvelope->envout_dB()*NoteGlobalPar.AmpLfo->amplfoout();
  111.  
  112.     NoteGlobalPar.GlobalFilterL=new Filter(pars->GlobalFilter);
  113.     NoteGlobalPar.GlobalFilterR=new Filter(pars->GlobalFilter);
  114.     
  115.     NoteGlobalPar.FilterEnvelope=new Envelope(pars->FilterEnvelope,basefreq);
  116.     NoteGlobalPar.FilterLfo=new LFO(pars->FilterLfo,basefreq);
  117.     NoteGlobalPar.FilterQ=pars->GlobalFilter->getq();
  118.     NoteGlobalPar.FilterFreqTracking=pars->GlobalFilter->getfreqtracking(basefreq);
  119.     
  120.     ready=1;///sa il pun pe asta doar cand e chiar gata
  121.  
  122.     if (parameters->sample[nsample].smp==NULL){
  123.     finished_=true;
  124.     return;
  125.     };
  126. };
  127.  
  128. PADnote::~PADnote(){
  129.     delete (NoteGlobalPar.FreqEnvelope);
  130.     delete (NoteGlobalPar.FreqLfo);
  131.     delete (NoteGlobalPar.AmpEnvelope);
  132.     delete (NoteGlobalPar.AmpLfo);
  133.     delete (NoteGlobalPar.GlobalFilterL);
  134.     delete (NoteGlobalPar.GlobalFilterR);
  135.     delete (NoteGlobalPar.FilterEnvelope);
  136.     delete (NoteGlobalPar.FilterLfo);
  137.     delete (tmpwave);
  138. };
  139.  
  140.  
  141. inline void PADnote::fadein(REALTYPE *smps){
  142.     int zerocrossings=0;
  143.     for (int i=1;i<SOUND_BUFFER_SIZE;i++)
  144.     if ((smps[i-1]<0.0) && (smps[i]>0.0)) zerocrossings++;//this is only the possitive crossings
  145.  
  146.     REALTYPE tmp=(SOUND_BUFFER_SIZE-1.0)/(zerocrossings+1)/3.0;
  147.     if (tmp<8.0) tmp=8.0;
  148.  
  149.     int n;
  150.     F2I(tmp,n);//how many samples is the fade-in    
  151.     if (n>SOUND_BUFFER_SIZE) n=SOUND_BUFFER_SIZE;
  152.     for (int i=0;i<n;i++) {//fade-in
  153.     REALTYPE tmp=0.5-cos((REALTYPE)i/(REALTYPE) n*PI)*0.5;
  154.     smps[i]*=tmp;
  155.     };
  156. };
  157.  
  158.  
  159. void PADnote::computecurrentparameters(){
  160.     REALTYPE globalpitch,globalfilterpitch;
  161.     globalpitch=0.01*(NoteGlobalPar.FreqEnvelope->envout()+
  162.     NoteGlobalPar.FreqLfo->lfoout()*ctl->modwheel.relmod+NoteGlobalPar.Detune);
  163.     globaloldamplitude=globalnewamplitude;
  164.     globalnewamplitude=NoteGlobalPar.Volume*NoteGlobalPar.AmpEnvelope->envout_dB()*NoteGlobalPar.AmpLfo->amplfoout();
  165.     
  166.     globalfilterpitch=NoteGlobalPar.FilterEnvelope->envout()+NoteGlobalPar.FilterLfo->lfoout()
  167.                       +NoteGlobalPar.FilterCenterPitch;
  168.               
  169.     REALTYPE tmpfilterfreq=globalfilterpitch+ctl->filtercutoff.relfreq
  170.             +NoteGlobalPar.FilterFreqTracking;
  171.     
  172.     tmpfilterfreq=NoteGlobalPar.GlobalFilterL->getrealfreq(tmpfilterfreq);
  173.     
  174.     REALTYPE globalfilterq=NoteGlobalPar.FilterQ*ctl->filterq.relq;
  175.     NoteGlobalPar.GlobalFilterL->setfreq_and_q(tmpfilterfreq,globalfilterq);
  176.     NoteGlobalPar.GlobalFilterR->setfreq_and_q(tmpfilterfreq,globalfilterq);
  177.  
  178.     //compute the portamento, if it is used by this note
  179.     REALTYPE portamentofreqrap=1.0;    
  180.     if (portamento!=0){//this voice use portamento
  181.     portamentofreqrap=ctl->portamento.freqrap;
  182.     if (ctl->portamento.used==0){//the portamento has finished
  183.         portamento=0;//this note is no longer "portamented"
  184.     };
  185.     };
  186.  
  187.     realfreq=basefreq*portamentofreqrap*pow(2.0,globalpitch/12.0)*ctl->pitchwheel.relfreq;
  188. };
  189.  
  190.  
  191. int PADnote::Compute_Linear(REALTYPE *outl,REALTYPE *outr,int freqhi,REALTYPE freqlo){
  192.     REALTYPE *smps=pars->sample[nsample].smp;
  193.     if (smps==NULL){
  194.     finished_=true;
  195.     return(1);
  196.     };
  197.     int size=pars->sample[nsample].size;
  198.     for (int i=0;i<SOUND_BUFFER_SIZE;i++){
  199.     poshi_l+=freqhi;
  200.     poshi_r+=freqhi;
  201.     poslo+=freqlo; 
  202.     if (poslo>=1.0){
  203.         poshi_l+=1;
  204.         poshi_r+=1;
  205.         poslo-=1.0;
  206.     };
  207.     if (poshi_l>=size) poshi_l%=size;
  208.     if (poshi_r>=size) poshi_r%=size;
  209.  
  210.     outl[i]=smps[poshi_l]*(1.0-poslo)+smps[poshi_l+1]*poslo;
  211.     outr[i]=smps[poshi_r]*(1.0-poslo)+smps[poshi_r+1]*poslo;
  212.     };
  213.     return(1);
  214. };
  215. int PADnote::Compute_Cubic(REALTYPE *outl,REALTYPE *outr,int freqhi,REALTYPE freqlo){
  216.     REALTYPE *smps=pars->sample[nsample].smp;
  217.     if (smps==NULL){
  218.     finished_=true;
  219.     return(1);
  220.     };
  221.     int size=pars->sample[nsample].size;
  222.     REALTYPE xm1,x0,x1,x2,a,b,c;
  223.     for (int i=0;i<SOUND_BUFFER_SIZE;i++){
  224.     poshi_l+=freqhi;
  225.     poshi_r+=freqhi;
  226.     poslo+=freqlo; 
  227.     if (poslo>=1.0){
  228.         poshi_l+=1;
  229.         poshi_r+=1;
  230.         poslo-=1.0;
  231.     };
  232.     if (poshi_l>=size) poshi_l%=size;
  233.     if (poshi_r>=size) poshi_r%=size;
  234.  
  235.  
  236.        //left
  237.        xm1=smps[poshi_l];
  238.        x0=smps[poshi_l + 1];
  239.        x1=smps[poshi_l + 2];
  240.        x2=smps[poshi_l + 3];
  241.        a = (3.0 * (x0-x1) - xm1 + x2)*0.5;
  242.        b = 2.0*x1 + xm1 - (5.0*x0 + x2)*0.5;
  243.        c = (x1 - xm1)*0.5;
  244.        outl[i] = (((a * poslo) + b) * poslo + c) * poslo + x0;    
  245.        //right
  246.        xm1=smps[poshi_r];
  247.        x0=smps[poshi_r + 1];
  248.        x1=smps[poshi_r + 2];
  249.        x2=smps[poshi_r + 3];
  250.        a = (3.0 * (x0-x1) - xm1 + x2)*0.5;
  251.        b = 2.0*x1 + xm1 - (5.0*x0 + x2)*0.5;
  252.        c = (x1 - xm1)*0.5;
  253.        outr[i] = (((a * poslo) + b) * poslo + c) * poslo + x0;    
  254.     };
  255.     return(1);
  256. };
  257.  
  258.  
  259. int PADnote::noteout(REALTYPE *outl,REALTYPE *outr){
  260.     computecurrentparameters();
  261.     REALTYPE *smps=pars->sample[nsample].smp;
  262.     if (smps==NULL){
  263.     for (int i=0;i<SOUND_BUFFER_SIZE;i++){
  264.         outl[i]=0.0;
  265.         outr[i]=0.0;
  266.     };
  267.     return(1);
  268.     };
  269.     REALTYPE smpfreq=pars->sample[nsample].basefreq;
  270.  
  271.     
  272.     REALTYPE freqrap=realfreq/smpfreq;
  273.     int freqhi=(int) (floor(freqrap));
  274.     REALTYPE freqlo=freqrap-floor(freqrap);
  275.  
  276.     
  277.     if (config.cfg.Interpolation) Compute_Cubic(outl,outr,freqhi,freqlo);
  278.     else Compute_Linear(outl,outr,freqhi,freqlo);
  279.     
  280.     
  281.     if (firsttime){
  282.     fadein(outl);
  283.     fadein(outr);
  284.     firsttime=false;
  285.     };
  286.  
  287.       NoteGlobalPar.GlobalFilterL->filterout(outl); 
  288.       NoteGlobalPar.GlobalFilterR->filterout(outr); 
  289.  
  290.      //Apply the punch
  291.      if (NoteGlobalPar.Punch.Enabled!=0){
  292.     for (int i=0;i<SOUND_BUFFER_SIZE;i++){
  293.         REALTYPE punchamp=NoteGlobalPar.Punch.initialvalue*NoteGlobalPar.Punch.t+1.0;
  294.         outl[i]*=punchamp;
  295.         outr[i]*=punchamp;
  296.         NoteGlobalPar.Punch.t-=NoteGlobalPar.Punch.dt;
  297.         if (NoteGlobalPar.Punch.t<0.0) {
  298.         NoteGlobalPar.Punch.Enabled=0;
  299.         break;
  300.         };
  301.         }; 
  302.         };
  303.  
  304.         if (ABOVE_AMPLITUDE_THRESHOLD(globaloldamplitude,globalnewamplitude)){
  305.     // Amplitude Interpolation
  306.             for (int i=0;i<SOUND_BUFFER_SIZE;i++){
  307.         REALTYPE tmpvol=INTERPOLATE_AMPLITUDE(globaloldamplitude,globalnewamplitude,i,SOUND_BUFFER_SIZE);
  308.             outl[i]*=tmpvol*NoteGlobalPar.Panning;
  309.         outr[i]*=tmpvol*(1.0-NoteGlobalPar.Panning); 
  310.             };
  311.     } else { 
  312.         for (int i=0;i<SOUND_BUFFER_SIZE;i++) {
  313.         outl[i]*=globalnewamplitude*NoteGlobalPar.Panning;
  314.         outr[i]*=globalnewamplitude*(1.0-NoteGlobalPar.Panning);
  315.         };
  316.         };
  317.  
  318.       
  319.      // Check if the global amplitude is finished. 
  320.      // If it does, disable the note     
  321.      if (NoteGlobalPar.AmpEnvelope->finished()!=0) {
  322.         for (int i=0;i<SOUND_BUFFER_SIZE;i++) {//fade-out
  323.         REALTYPE tmp=1.0-(REALTYPE)i/(REALTYPE)SOUND_BUFFER_SIZE;
  324.         outl[i]*=tmp;
  325.         outr[i]*=tmp;
  326.         };
  327.         finished_=1;
  328.      };
  329.  
  330.     return(1);
  331. };
  332.  
  333. int PADnote::finished(){
  334.     return(finished_);
  335. };
  336.  
  337. void PADnote::relasekey(){
  338.   NoteGlobalPar.FreqEnvelope->relasekey();
  339.   NoteGlobalPar.FilterEnvelope->relasekey();
  340.   NoteGlobalPar.AmpEnvelope->relasekey();
  341. };
  342.  
  343.